<html>
<head><meta charset="utf-8"><title>Adding saturated shift operations to libcore? · t-libs · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/index.html">t-libs</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html">Adding saturated shift operations to libcore?</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="246128860"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246128860" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Egger <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246128860">(Jul 15 2021 at 17:33)</a>:</h4>
<p>Hi. I noticed that we currently don't seem to have saturated shift operations. This can be a useful operation which is natively supported by LLVM intrinsics and some ISAs. Is there interest to add those operations to the primitive types?</p>



<a name="246129427"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246129427" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246129427">(Jul 15 2021 at 17:36)</a>:</h4>
<p>Could you give and example, I'm not sure i follow. Is it a shift that shifts up to the maximum allowable possible number of bits?</p>



<a name="246129895"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246129895" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Egger <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246129895">(Jul 15 2021 at 17:40)</a>:</h4>
<p><a href="https://llvm.org/docs/LangRef.html#llvm-sshl-sat-intrinsics">https://llvm.org/docs/LangRef.html#llvm-sshl-sat-intrinsics</a></p>



<a name="246130605"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246130605" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Egger <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246130605">(Jul 15 2021 at 17:46)</a>:</h4>
<p>It does basically the same as other saturating operations just for shift operations: if the resulting value of the shift operation would end up outside of the range of the type it is clamped to the maximum or minimum value of the type.</p>



<a name="246144263"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246144263" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246144263">(Jul 15 2021 at 19:34)</a>:</h4>
<p>see also <a href="#narrow/stream/219381-t-libs/topic/Pre-RFC.3A.20saturating_shl.2Fshr.20on.20integer.20types/near/243114701">https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Pre-RFC.3A.20saturating_shl.2Fshr.20on.20integer.20types/near/243114701</a></p>



<a name="246157354"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246157354" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Egger <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246157354">(Jul 15 2021 at 21:13)</a>:</h4>
<p><span class="user-mention silent" data-user-id="138448">cuviper</span> <a href="#narrow/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F/near/246144263">said</a>:</p>
<blockquote>
<p>see also <a href="#narrow/stream/219381-t-libs/topic/Pre-RFC.3A.20saturating_shl.2Fshr.20on.20integer.20types/near/243114701">https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Pre-RFC.3A.20saturating_shl.2Fshr.20on.20integer.20types/near/243114701</a></p>
</blockquote>
<p>Interesting but slightly different as far as I can tell. That proposal seems to be that shifting more than amount of bits in the type was legalized, whereas with the LLVM intrinsic that is still illegal. Also the discussion seems to predate the actual inclusion of the intrinsics, here's the patch which added it with some more motivation: <a href="https://reviews.llvm.org/D83216">https://reviews.llvm.org/D83216</a></p>



<a name="246169442"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246169442" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246169442">(Jul 15 2021 at 23:39)</a>:</h4>
<p>if nothing else, it reminds us that there are multiple interpretations of "saturating" in this space</p>



<a name="246169556"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246169556" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246169556">(Jul 15 2021 at 23:41)</a>:</h4>
<p>we already have checked/overflowing/wrapping shifts that are only speaking of the rhs vs. bit width</p>



<a name="246171199"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246171199" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Egger <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246171199">(Jul 16 2021 at 00:07)</a>:</h4>
<p>Indeed. But similarly to other saturated operations, saturated shifts also have very common usecases especially in fixed point calculations in audio applications running on microcontrollers, which is coincidentally where I'm coming from. <span aria-label="sweat smile" class="emoji emoji-1f605" role="img" title="sweat smile">:sweat_smile:</span>For me this starts to look like a chicken/egg problem; I'd simply like to use this stuff for which I need to be able to call the intrinsics, however <span class="user-mention" data-user-id="123586">@nagisa</span> pointed me here because the compiler team is not keen on adding intrinsics without users in libcore/libstd. <span aria-label="shrug" class="emoji emoji-1f937" role="img" title="shrug">:shrug:</span>🏻‍♂️</p>



<a name="246180868"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246180868" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246180868">(Jul 16 2021 at 03:25)</a>:</h4>
<p>Very odd to ask that there be users of something that doesn't exist yet.</p>



<a name="246181046"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246181046" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246181046">(Jul 16 2021 at 03:29)</a>:</h4>
<p>But anyway, I think that saturating shift wouldn't be a good term because in all other cases the modifier applies to the shift amount.</p>
<p>though i don't immediately know a better term to use for an output-modified shift. output_saturating_shift seems very poor.</p>



<a name="246193534"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246193534" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246193534">(Jul 16 2021 at 07:38)</a>:</h4>
<p>Intrinsics are an implementation detail. Figure out an API that needs them in their implementation and add these intrinsics as part of implementing an API.</p>



<a name="246193616"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246193616" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246193616">(Jul 16 2021 at 07:39)</a>:</h4>
<p>Alternatively said - intrinsics are never going to be stable (with very few exceptions, think transmute) so it doesn't make much sense to add them in isolation, or use them directly.</p>



<a name="246193927"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246193927" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246193927">(Jul 16 2021 at 07:44)</a>:</h4>
<p>This is especially relevant because these intrinsics will need implementation in miri and other backends too. It is no longer just adding a line in llvm specific file.</p>



<a name="246196548"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246196548" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Egger <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246196548">(Jul 16 2021 at 08:19)</a>:</h4>
<p><span class="user-mention silent" data-user-id="224471">Lokathor</span> <a href="#narrow/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F/near/246181046">said</a>:</p>
<blockquote>
<p>But anyway, I think that saturating shift wouldn't be a good term because in all other cases the modifier applies to the shift amount.</p>
<p>though i don't immediately know a better term to use for an output-modified shift. output_saturating_shift seems very poor.</p>
</blockquote>
<p>The name is in line with the LLVM name, the other saturating methods we already have in Rust and the ARM instruction I would like to use: <a href="https://www.keil.com/support/man/docs/armasm/armasm_dom1361289904320.htm">https://www.keil.com/support/man/docs/armasm/armasm_dom1361289904320.htm</a> . I can't think of any better suited name really.</p>



<a name="246222688"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246222688" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246222688">(Jul 16 2021 at 13:30)</a>:</h4>
<p>But the other non-shift ops aren't consistent with the shift ops, and so this saturating_shl becomes inconsistent with all other shl ops.</p>
<ul>
<li>checked_shl: performs the check based on the shift amount.</li>
<li>wrapping_shl: performs the wrap on the shift amount.</li>
<li>overflowing_shl: performs the overflow calculation on the shift amount.</li>
</ul>
<p>And now saturating_shl doesn't saturate the shift amount, it saturates the final output value.</p>



<a name="246238703"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246238703" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jacob Lifshay <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246238703">(Jul 16 2021 at 15:31)</a>:</h4>
<p>well, I'd say the current semantics of <code>&lt;&lt;</code>, <code>checked_shl</code>, and <code>overflowing_shl</code> are flawed, since until now I expected them to check for overflow in the final value, so <code>0x10u32 &lt;&lt; 31</code> should have been specified to panic in debug mode. I think having <code>saturating_shl</code> saturate the output value is the right semantics.</p>



<a name="246245563"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246245563" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246245563">(Jul 16 2021 at 16:23)</a>:</h4>
<p>those flaws are stable though, so I'd still lean toward consistency if we add <code>saturating_shl</code>.</p>



<a name="246245700"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246245700" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246245700">(Jul 16 2021 at 16:24)</a>:</h4>
<p>I do think value-saturation would be valuable, and maybe also checked/overflowing versions of that, but they need distinct names</p>



<a name="246265829"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246265829" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> isHavvy <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246265829">(Jul 16 2021 at 19:09)</a>:</h4>
<p><code>checked_value_shl</code></p>



<a name="246271624"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246271624" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Egger <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246271624">(Jul 16 2021 at 20:02)</a>:</h4>
<p><span class="user-mention silent" data-user-id="296643">isHavvy</span> <a href="#narrow/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F/near/246265829">said</a>:</p>
<blockquote>
<p><code>checked_value_shl</code></p>
</blockquote>
<p>Urgh. Really the only problem I see with <code>saturating_shl</code> is that it's pretty much only a limited version of <code>saturating_mul</code>.</p>



<a name="246291042"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246291042" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Egger <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246291042">(Jul 16 2021 at 23:19)</a>:</h4>
<p><span class="user-mention silent" data-user-id="138448">cuviper</span> <a href="#narrow/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F/near/246245563">said</a>:</p>
<blockquote>
<p>those flaws are stable though, so I'd still lean toward consistency if we add <code>saturating_shl</code>.</p>
</blockquote>
<p>But why is the consistency between all <code>_shl</code> operations rated higher than the consistency between all <code>saturating_</code> ops? To me the prefix is the important bit defining how exactly an operation will be carried out. I think a user automatically has a certain behavioral expectation when they see <code>checked_</code>, <code>saturating_</code> or <code>unchecked_</code> in the function name.</p>



<a name="246292304"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246292304" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246292304">(Jul 16 2021 at 23:44)</a>:</h4>
<p>it could be argued either way, sure, but consistent <code>_shl</code> is better IMO.</p>



<a name="246292313"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246292313" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246292313">(Jul 16 2021 at 23:44)</a>:</h4>
<p>There's a real relationship between these variations. If <code>checked_foo</code> returns <code>None</code>, I expect <code>saturating_foo</code> to saturate. If <code>checked_foo</code> returns <code>Some(value)</code>, I expect <code>saturating_foo</code> to return the exact same <code>value</code>.</p>



<a name="246292351"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/Adding%20saturated%20shift%20operations%20to%20libcore%3F/near/246292351" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/Adding.20saturated.20shift.20operations.20to.20libcore.3F.html#246292351">(Jul 16 2021 at 23:45)</a>:</h4>
<p>that expectation is broken if <code>checked_shl</code> only looks at the shift amount, while <code>saturating_shl</code> in concerned with value overflow.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>